﻿using COC.CEvent;
using Ionic.BZip2;
using UnityEngine;
using System.Collections.Generic;
using COC.Threading;

namespace COC.Tools.Pathing
{
    public sealed class PathFindingPool : CThreadPool
    {
        #region properties
        private static CThreadFactory cf;
        private static PathFindingPool pool;
        public static CEventQueue mDoQueue=new CEventQueue();
        public static CEventQueue mFutureQueue=new CEventQueue();
        static CThreadPoolInfo mThreadPoolInfo;
        static CThreadPool.CThreadFactory mFactory;

        #endregion
        #region a star parameters
        private static PathfindingMath aStarMath;
        private static CTile[,] obstacleMap;
        #endregion


        public PathFindingPool(string name, int size, CEventQueue doQueue, CEventQueue futureQueue, CThreadFactory factory, CThreadPoolInfo threadPoolInfo) : base(name, size, doQueue, futureQueue, factory, threadPoolInfo)
        {

        }
      
        public  static PathFindingPool getInstance(bool background,int size,float width,float height,float tileSize,float offset,CTile[,] obstacles)
        {
            if (pool == null)
            {
                mFactory=Instance();
                CThreadPoolInfo threadPoolInfo=new CThreadPoolInfo();
                threadPoolInfo.isBackgound = background;
                mThreadPoolInfo=threadPoolInfo;
                pool = new PathFindingPool(PathFindingConstant.PATH_FINDING_THREAD_POOL, size, mDoQueue, mFutureQueue, mFactory, mThreadPoolInfo);
            }
            obstacleMap = obstacles;
            aStarMath = PathfindingMath.getInstance();
            aStarMath.Initial();
            aStarMath.configuration(new float[]{width,height,tileSize,offset},obstacleMap);
            return pool;
        }
        /// <summary>
        /// inject of obstacle layer. 
        /// </summary>
        /// <param name="obstacles"></param>
        public void setObstacleMap(CTile[,] obstacles)
        {
            if (obstacleMap != null)
                obstacleMap = null;
            obstacleMap = obstacles;
        }
      
        public PathfindingMath getPathfindingMath()
        {
            return aStarMath;
        }
        public static CThreadFactory Instance()
        {
            if (cf == null)
            {
                cf = new CThreadFactory();
                cf.ExcuteMethod += doExecute;
                //cf.maxStackSize
            }
            return cf;
        }

        static Object doExecute(WorkEventItem eventItem)
        {
            CPath p=null;
            PathInfo.PathState state;
            switch (eventItem.type)
            {
                case CEventAction.ACTION_PATH_FINDING:

                    UnityEngine.Debug.Log("Event:Path finding");
                    p=(CPath)eventItem.arg;
                    UnityEngine.Debug.Log("[PATH START]:" + p.startingXY + ",[PATH TARGET]:" + p.targetXY);
                    state=aStarMath.searchingPath(p);
                    UnityEngine.Debug.Log("[PATH RESULT]:" + state + ",LENGTH:" + p.mPathInfo.length);
                    eventItem.isComplete = true;
                    eventItem.isError = false;
                    break;
                default:
                    break;
            }
            return null;
        }


    }
}
